package controller

import (
	"errors"
	"fmt"
	"strconv"

	"gitee.com/liuyun-luo/MagicStreamMovies/Server/global"
	"gitee.com/liuyun-luo/MagicStreamMovies/Server/models"
	"gitee.com/liuyun-luo/MagicStreamMovies/Server/utils"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// 收藏电影
func CollectionMovie(ctx *gin.Context) {
	//从URL中获取参数
	user_id := ctx.Param("user_id")
	if user_id == "" {
		ctx.JSON(400, gin.H{
			"error": "参数错误,user_id不能为空",
		})
		return
	}

	//从jwt中获取用户ID，进行对比，防止他人修改url中的id
	id, err := utils.GetUserIdFromContext(ctx)
	if err != nil {
		ctx.JSON(500, gin.H{
			"error": "jwt解析失败，err: " + err.Error(),
		})
		return
	}
	if id != user_id {
		ctx.JSON(403, gin.H{
			"error": "您无权执行此操作!",
		})
		return
	}

	//从URL中获取参数
	movie_id := ctx.Param("movie_id")
	if movie_id == "" {
		ctx.JSON(400, gin.H{
			"error": "参数错误,movie_id不能为空",
		})
		return
	}


	//查询电影
	var movie models.Movie
	if err := global.MySQLDb.First(&movie, movie_id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) { //如果没有查询到
			ctx.JSON(404, gin.H{
				"error": fmt.Sprintf("未找到id为%v的电影,err: %s", movie_id, err.Error()),
			})
		} else {
			ctx.JSON(500, gin.H{
				"error": "数据库查询失败，err: " + err.Error(),
			})
		}
		return
	}

	//查询用户
	var user models.User
	if err := global.MySQLDb.First(&user, user_id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) { //如果没有查询到
			ctx.JSON(404, gin.H{
				"error": fmt.Sprintf("未找到id为%v的用户,err: %s", user_id, err.Error()),
			})
		} else {
			ctx.JSON(500, gin.H{
				"error": "数据库查询失败，err: " + err.Error(),
			})
		}
		return
	}

	//启动事务--添加收藏关系
	if err := global.MySQLDb.Transaction(func(tx *gorm.DB) error {
		userId, err := strconv.ParseUint(user_id, 10, 64)
		if err != nil {
			return fmt.Errorf("字符串转整数失败,err: %v", err)
		}
		movieId, err := strconv.ParseUint(movie_id, 10, 64)
		if err != nil {
			return fmt.Errorf("字符串转整数失败,err: %v", err)
		}

		//添加关联关系
		if err := tx.Create(&models.UserMovieCollect{
			UserId:  uint(userId),
			MovieId: uint(movieId),
		}).Error; err != nil {
			return fmt.Errorf("添加收藏关系失败,err: %v", err)
		}

		//电影的收藏总数+1
		if err := tx.Model(&movie).Where("id = ?", movie_id).Update("collect_count", gorm.Expr("collect_count + ?", 1)).Error; err != nil {
			return fmt.Errorf("收藏总数+1失败,err: %v", err)
		}

		return nil
	}); err != nil {
		ctx.JSON(500, gin.H{
			"error": err.Error(),
		})
		return
	}

	//返回成功信息
	ctx.JSON(200, gin.H{
		"msg": "收藏成功！",
	})
}

// 获取收藏的电影--游标分页
func GetCollectionMovies(ctx *gin.Context) {
	type cursorInputDTO struct {
		//起始游标（本质是电影的ID，首次请求时可为0）
		Cursor uint `json:"cursor"`
		//请求的电影的数量
		PageSize uint `binding:"required" json:"page_size"`
		//电影的类别
		Category string `json:"category"`
		//排序方式
		SortBy string `json:"sort_by" binding:"required,oneof=rating like_count play_count collect_count created_at"`
		//排序方向
		SortDirection string `json:"sort_direction" binding:"required,oneof=desc asc"`
		//发起请求的用户的id
		UserId uint `json:"user_id" binding:"required"`
	}

	var input cursorInputDTO

	//从URL中获取参数
	user_id := ctx.Param("user_id")
	if user_id == "" {
		ctx.JSON(400, gin.H{
			"error": "参数错误,user_id不能为空",
		})
		return
	}

	//从jwt中获取用户ID，进行对比，防止他人修改url中的id
	id, err := utils.GetUserIdFromContext(ctx)
	if err != nil {
		ctx.JSON(500, gin.H{
			"error": "jwt解析失败，err: " + err.Error(),
		})
		return
	}
	if id != user_id {
		ctx.JSON(403, gin.H{
			"error": "您无权执行此操作!",
		})
		return
	}

	//读取参数
	if err := ctx.ShouldBindJSON(&input); err != nil {
		ctx.JSON(400, gin.H{
			"error": "参数错误,err: " + err.Error(),
		})
		return
	}

	var movies []models.Movie
	var nextCursor uint

	db := global.MySQLDb

	// 构建基础查询
	// 先筛选出user_id收藏的所有电影
	query := db.Model(&models.Movie{}).Joins("JOIN user_movie_collects ON movies.id = user_movie_collects.movie_id").
		Joins("JOIN users ON user_movie_collects.user_id = users.id").
		Where("users.id = ?", user_id)

	// 1. 按电影类别筛选
	if input.Category != "" {
		query = query.Joins("JOIN movie_genres ON movies.id = movie_genres.movie_id").
			Joins("JOIN genres ON movie_genres.genre_id = genres.id").
			Where("genres.genre_name = ?", input.Category).
			Group("movies.id")
	}

	// 2. 处理游标分页
	if input.Cursor > 0 {
		// 获取当前游标位置的电影记录，用于后续比较
		var currentMovie models.Movie
		if err := db.First(&currentMovie, input.Cursor).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				ctx.JSON(404, gin.H{
					"error": "找不到游标对应的电影,err: " + err.Error(),
				})
			} else {
				ctx.JSON(500, gin.H{
					"error": "数据库执行查询操作错误,err: " + err.Error(),
				})
			}
			return
		}

		// 解析排序字段和排序方向
		var sortField, sortDirection string = input.SortBy, input.SortDirection

		if sortDirection != "asc" { //如果不是升序
			sortDirection = "desc"
		}

		// 根据排序字段和方向构建游标条件
		switch sortField {
		case "rating": //按评分排序
			if sortDirection == "desc" {
				query = query.Where("rating < ? OR (rating = ? AND movies.id >= ? )",
					currentMovie.Rating, currentMovie.Rating, input.Cursor)
			} else {
				query = query.Where("rating > ? OR (rating = ? AND movies.id >= ?)",
					currentMovie.Rating, currentMovie.Rating, input.Cursor)
			}
		case "like_count": //按点赞排序
			if sortDirection == "desc" {
				query = query.Where("like_count < ? OR (like_count = ? AND movies.id >= ?)",
					currentMovie.LikeCount, currentMovie.LikeCount, input.Cursor)
			} else {
				query = query.Where("like_count > ? OR (like_count = ? AND movies.id >= ?)",
					currentMovie.LikeCount, currentMovie.LikeCount, input.Cursor)
			}
		case "play_count": //按播放量排序
			if sortDirection == "desc" {
				query = query.Where("play_count < ? OR (play_count = ? AND movies.id >= ?)",
					currentMovie.PlayCount, currentMovie.PlayCount, input.Cursor)
			} else {
				query = query.Where("play_count > ? OR (play_count = ? AND movies.id >= ?)",
					currentMovie.PlayCount, currentMovie.PlayCount, input.Cursor)
			}
		case "collect_count": //按收藏排序
			if sortDirection == "desc" {
				query = query.Where("collect_count < ? OR (collect_count = ? AND movies.id >= ?)",
					currentMovie.CollectCount, currentMovie.CollectCount, input.Cursor)
			} else {
				query = query.Where("collect_count > ? OR (collect_count = ? AND movies.id >= ?)",
					currentMovie.CollectCount, currentMovie.CollectCount, input.Cursor)
			}
		case "created_at": //按电影创建的时间排序
			if sortDirection == "desc" {
				query = query.Where("created_at < ? OR (created_at = ? AND movies.id >= ?)",
					currentMovie.CreatedAt, currentMovie.CreatedAt, input.Cursor)
			} else {
				query = query.Where("created_at > ? OR (created_at = ? AND movies.id >= ?)",
					currentMovie.CreatedAt, currentMovie.CreatedAt, input.Cursor)
			}
		default:
			// ID大于游标即可
			query = query.Where("movies.id >= ?", input.Cursor)
		}
	} else if input.Cursor == 0 { //首次分页请求为游标为0
		// ID大于游标即可
		query = query.Where("movies.id >= ?", input.Cursor)
	}

	// 3. 应用排序
	query = query.Order(input.SortBy + " " + input.SortDirection)

	// 4. 查询比请求数量多一条记录，用于判断是否还有下一页
	query = query.Limit(int(input.PageSize) + 1)

	// 执行查询
	if err := query.Preload("GenreList").Find(&movies).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			ctx.JSON(404, gin.H{
				"error": "找不到游标对应的电影,err: " + err.Error(),
			})
		} else {
			ctx.JSON(500, gin.H{
				"error": "数据库执行查询操作错误,err: " + err.Error(),
			})
		}
		return
	}

	// 5. 处理结果，设置下一个游标
	if len(movies) > int(input.PageSize) {
		// 有下一页，返回第input.PageSize条记录的ID作为下一个游标
		nextCursor = movies[input.PageSize].ID
		movies = movies[:input.PageSize] // 截断结果
	} else {
		nextCursor = 0 // 没有下一页
	}

	ctx.JSON(200, gin.H{
		"movies":      movies,
		"next_cursor": nextCursor,
	})
}
